package com.coolw.spring.interceptor;

import com.coolw.spring.config.WebConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 拦截器
 * <p>HandlerInterceptor接口
 * <pre>
 *      1.preHandle：目标方法执行前执行。如果该方法返回false，则当前请求结束，其他的拦截器也不再执行。可以做一些初始化工作
 *      2.postHandle：只有preHandle方法返回true才会执行，会在Controller方法执行之后，DispatcherServlet返回渲染视图之前执行
 *      3.afterCompletion：只有preHandle方法返回true才会执行，在整个请求结束之后，DispatcherServlet渲染视图之后执行。可以做一些清理工作
 *  注意：postHandle方法被调用的顺序和preHandle方法是相反的，先声明的拦截器preHandle方法先执行，而postHandle方法反而会后执行
 *  {@link DispatcherServlet#doDispatch}：<code>applyPreHandle 循环正序</code> | <code>applyPostHandle 循环倒序</code>
 * </pre>
 *
 * <p>适用场景：权限、日志、统计等等
 *
 * <p>实现原理：基于java的反射机制（动态代理）实现的
 *
 * <p>生命周期：拦截器是在请求进入Servlet之后，在进入Controller之前进行预处理的，Controller中渲染视图之后请求结束
 *
 * <p>作用范围：拦截器只会对Controller请求和访问static目录下的静态资源起作用
 *
 * <p> 实现步骤
 * <pre>
 *      1.实现HandlerInterceptor接口定义拦截器
 *      2.将该拦截器注册到spring容器 {@link WebConfig}
 * </pre>
 *
 * @author coolw
 * @date 2022/10/12 9:42
 */
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        log.info("用户认证拦截器-目标方法执行前处理");
        String uri = request.getRequestURI();
        return checkAuth(uri);
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        log.info("用户认证拦截器-目标方法执行后处理");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        log.info("用户认证拦截器-请求完成处理");
    }

    private boolean checkAuth(String uri) {
        //  用户认证处理
        return true;
    }
}
